/* 
 * Bitmain Tech, Home of Professional Bitmain Tech
 * Copyright 2014 Bitmain Tech Inc. and/or its affiliates and other contributors
 * as indicated by the @author tags. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 */
package com.bitmain.mmst.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.bitmain.ulnar.aider.DateAider;

/**
 * 通用工具类
 *
 * @author Kweny - enkun.jiang@bitmain.com
 * @since 2016年1月30日
 *
 */
public class CommonUtil {
	private static Logger logger = Logger.getLogger(CommonUtil.class);
	
	public static String generateMineNodeSerial() {
		return UUID.randomUUID().toString().substring(0, 8).toLowerCase();
	}
	
	private static Pattern firmwareVersionPattern = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");
	public static boolean isFirmwareVersion(String input) {
		boolean match = firmwareVersionPattern.matcher(input).matches();
		if (!match) {
			return false;
		}
		int year = Integer.parseInt(input.substring(0, 4));
		int month = Integer.parseInt(input.substring(4, 6)) - 1;
		int day = Integer.parseInt(input.substring(6, 8));
		Calendar c = Calendar.getInstance();
		c.set(year, month, day);
		return c.get(Calendar.YEAR) == year && c.get(Calendar.MONTH) == month && c.get(Calendar.DAY_OF_MONTH) == day;
	}
	
	/**
     * 根据矿机固件编译时间获取版本号
     * 
     * @param compileTime 固件编译时间，如：Tue Aug  4 17:27:43 CST 2015
     * @return 固件版本号，如：20150804
     */
    public static String formatFirmwareVersion(String compileTime) {
    	String version = StringUtils.EMPTY;
    	if(StringUtils.isNotEmpty(compileTime)){
    		try {
    			SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy",Locale.US);
    			//先将字符串转化成为日期对象
				Date date = sdf.parse(compileTime);
				//将日期对象转化为固定格式字符串
				version = DateAider.formatDate(date, "yyyymmdd");
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	return version;
    }
    
    /**
	 * 从指定数组中取最小值和最大值
	 * 
	 * @param array 指定数组，
	 * @return 返回一个长度为2的数组，第一个元素是最小值，第二个元素是最大值
	 * 			<li>若参数为null或empty，则两个元素均为0；
	 * 			<li>若参数长度为1，则将参数中的数字与0进行比较并返回结果；
	 * 			<li>若参数长度为2，则返回根据参数元素大小排列的副本。
	 */
    public static int[] getExtremums(Integer[] array) {
    	return getExtremums(ArrayUtils.toPrimitive(array));
    }
	
	/**
	 * 从指定数组中取最小值和最大值
	 * 
	 * @param array 指定数组，
	 * @return 返回一个长度为2的数组，第一个元素是最小值，第二个元素是最大值
	 * 			<li>若参数为null或empty，则两个元素均为0；
	 * 			<li>若参数长度为1，则将参数中的数字与0进行比较并返回结果；
	 * 			<li>若参数长度为2，则返回根据参数元素大小排列的副本。
	 */
	public static int[] getExtremums(int[] array) {
		int length = array != null ? array.length : 0;
		switch (length) {
		case 0:
			return new int[] {0, 0};
		case 1:
			return array[0] < 0 ? new int[] {array[0], 0} : new int[] {0, array[0]};
		case 2:
			return array[0] < array[1] ? new int[] {array[0], array[1]} : new int[] {array[1], array[0]};
		default:
			int min = 0; // 最小值
			int max = 0; // 最大值
			int i = 0; // 循环索引
			/*
			 * 每次从数组中取两个数字（索引递增值为2），用较小值与最小值min比较；用较大值与最大值max比较，减少循环次数；
			 * 若数组长度为偶数，直接取出前两个数字，比较后分别赋值给min和max，后面的循环直接从第三个元素开始；
			 * 若数字的长度为奇数，取出第一个数字赋值给min和max，后面的循环直接从第二个元素开始；
			 */
			if (length % 2 == 0) {
				if (array[0] > array[1]) {
					max = array[0];
					min = array[1];
				} else {
					max = array[1];
					min = array[0];
				}
				i = 2;
			} else {
				max = min = array[0];
				i ++;
			}
			while (i < length) {
				if (array[i] > array[i + 1]) {
					if (array[i] > max) {
						max = array[i];
					}
					if (array[i + 1] < min) {
						min = array[i + 1];
					}
				} else {
					if (array[i + 1] > max) {
						max = array[i + 1];
					}
					if (array[i] < min) {
						min = array[i];
					}
				}
				i += 2;
			}
			return new int[] {min, max};
		}
	}
}
